/********************************************************************
    copyright (c) by tnmujoy
    @created:	10/10/2011   10:36
    @filename: 	Singleton
    @author:	Limiko Lau (limiko.lau@gmail.com)
    @brief:	    
*********************************************************************/

#ifndef TNMUJOY_GDUT_DESIGNPATTERN_SINGLETON_H_
#define TNMUJOY_GDUT_DESIGNPATTERN_SINGLETON_H_

#include <assert.h>
#include <list>

namespace tnmujoy
{
namespace gdut
{

template< typename T >
class Singleton
{
public:
    static T& instance( void )
    {  
        assert( getInstance() );  
        return ( *getInstance() );  
    }
    static T* instancePtr( void )
    {  
        return ( getInstance() ); 
    }
protected:
    Singleton( void )
    {
        assert( !getInstance() );
        getInstance() = static_cast< T* >( this );
    }
    virtual ~Singleton( void )
    {  
        assert( getInstance() ); 
        getInstance() = 0; 
    }
private:
    static T* & getInstance()
    {
        static T* sInstance =0 ;
        return sInstance;
    }
};



class SingletonClassInfo
{
public:
    void* (*createObject)();
    void (*destoryObject)(void* _object);
    SingletonClassInfo()
    {
        ClassObject = 0;
    }
    void* ClassObject;
};

template<typename T>
class SingletonClassCreator
{
public:
    static void* create()
    {
        return static_cast<void*>(new T());
    }
    static void destory(void* _object)
    {
        T* object = static_cast<T*>(_object);
        if(object)
        {
            delete object;
            object = 0;
        }
    }
};

class SingletonManager
{
public:
    static void initialize()
    {
        std::list<SingletonClassInfo>::iterator itr = getRegisteredClassList().begin();
        for (; itr != getRegisteredClassList().end(); ++itr)
        {
            itr->ClassObject = itr->createObject();
        }
    }
    static void release()
    {
        std::list<SingletonClassInfo>::iterator itr = getRegisteredClassList().begin();
        for (; itr != getRegisteredClassList().end(); ++itr)
        {
            itr->destoryObject(itr->ClassObject);
        }
    }

    template<typename T>
    static void registerClass(const T* _class)
    {
        SingletonClassInfo classInfo;
        classInfo.createObject = SingletonClassCreator<T>::create;
        classInfo.destoryObject = SingletonClassCreator<T>::destory;
        getRegisteredClassList().push_back(classInfo);
    }
protected:
private:
    static std::list<SingletonClassInfo>& getRegisteredClassList()
    {
        static std::list<SingletonClassInfo> registeredClassList;
        return registeredClassList;
    }
    
};

}//namespace gdut
}//namespace tnmujoy
    
#define REGISTER_SINGLETON_CLASS(classname)    \
   class singleton_##classname \
   { \
   public: \
       singleton_##classname() \
       { \
           tnmujoy::gdut::SingletonManager::registerClass((classname*)0); \
       } \
   }; \
   static singleton_##classname sSingleton_##classname;

#endif //TNMUJOY_GDUT_DESIGNPATTERN_SINGLETON_H_

//
//History:
//[10/10/2011] <limiko.lau@gmail.com> created